【社内勉強会】AKIBA.GCP でZennのCI/CDを紹介し、Google Cloud Japan の皆さまに改善アドバイスをいただきました
こんにちは。Zennチームの和田です。2023年3月1日、Google Cloud に関する社内勉強会が開催され、そこでZennのCI/CDの話をしたのでレポートを書きます。
Zenn の CI/CD
Zennは、バックエンドにGoogle Cloudを採用しています。少人数のチームで運営しており、できるだけ運用負荷を減らす観点でCI/CDは重視しているポイントです。いまは、以下のような概略図で動いています。
勉強会の目的
おおきくふたつありました。
- Google Cloud で動いているアプリのCI/CDとして、Zennを例にとって共有すること
- Google Cloud Japan の方々に改善点をアドバイスしてもらうこと
この勉強会のために、Google Cloud Japan の皆さまにクラスメソッドへ足を運んでいただきました。ありがとうございました。Google Cloud Japan様はZennのPublicationを利用いただいています。
参加メンバー
- グーグル・クラウド・ジャパン合同会社 アプリケーション モダナイゼーション スペシャリスト 頼兼孝幸
- グーグル・クラウド・ジャパン合同会社 アプリケーション モダナイゼーション スペシャリスト 塚越啓介
- グーグル・クラウド・ジャパン合同会社 アプリケーション モダナイゼーション スペシャリスト 諏訪悠紀
- グーグル・クラウド・ジャパン合同会社 パートナーエンジニア 平岡一成
- クラスメソッド株式会社 Zennチーム 和田祐介
GitHub Actions と Cloud Build
これらは Zenn の CI/CD でコアとなる仕組みです。
GitHub Actions
GitHub Actions は、デプロイに必要な成果物は生成せず、コード検査に集中します。
Cloud Build
Cloud Build は Google Cloud のサービスで、ZennではDockerイメージのビルドとプッシュ、そしてCloud Runへのデプロイで利用しています。「トリガー」と呼ばれる起動条件、具体的なビルドステップを定義するYAMLファイルがワンセットです。詳しくは公式ドキュメントを参照してください。
Cloud Build - サーバーレス CI / CD プラットフォームでビルド、テスト、デプロイ
リリースまでの流れ
これらの仕組みを使い、次のような流れでリリースしています。
- 開発者がプルリクエストを作成する
- GitHub Actions が起動し、コード検査が実行される
- GitHub Actions およびコードレビューにパスしたら、開発者がmainブランチへマージする
- Cloud Build が起動する
- docker コマンドが新しいコンテナイメージを作成する
- docker コマンドがコンテナイメージを Artifact Registry へプッシュする
- gcloud コマンドが Cloud Run の新しいリビジョンを作成する
- 開発者が Cloud Shell でトラフィックを流すコマンドを実行する
- リリース完了
リリースフローで気に入っているところ
- GitHub Actions はコード検査、Cloud Build はビルドとデリバリーという分担がわかりやすい
- GitHub Actions には Google Cloud などのアクセスキー・シークレットキーを入れない方針としており、安心感がある
- Cloud Shell でセキュアにリリースコマンドを実行できる
- 完全に自動化できておらず、人の手が入る部分もあるが、チーム規模を考えるといいバランスに落ち着いているという感触がある
CI/CD の課題点と、改善アドバイス
私が感じているこのパイプラインの課題と、それに対する Google Cloud Japan の方々からのアドバイスを併記します。
1. イメージ共通化
【課題】 検証環境と本番環境で同じコンテナイメージを使いたいが、Next.jsの仕様上むずかしい。Next.js がビルド時に環境変数を埋め込むため、いまはイメージを別にしています。イメージを共通化するためのいい方法があれば知りたい。
こちらの記事でも言及しています。
Zennのバックエンドを Google App Engine から Cloud Run へ移行しました
【改善アドバイス】 ブラウザから動的に値をとってくることと、ビルドイメージをわけることのトレードオフという認識です。たとえばSSRでブラウザ向けの環境変数を取得、Propsとして渡すことが許容できるならばビルド時に埋め込む環境変数をなくし、イメージを共通化できると思います。
2. イメージビルド時間の短縮
【課題】 Cloud Build で Ruby on Rails と Next.js のDockerイメージをビルドしているが、ここに5分以上時間がかかっていて、なんとか5分以内に収めたい。
【改善アドバイス】 イメージビルドのどのステップで時間を要しているかにもよりますが、一般的なアプローチとして以下を試してみるといいかもしれません:
- ビルド用の vCPU を増やす
- よりスリムなコンテナを使う
- GitHub Actions の Self-hosted runners を使い、性能をチューニングする
- Google Cloud の Cloud Run や App Engine でも Self-hosted runners として起動できる -- 参考: GitHub Actions self-hosted runners on Google Cloud | The GitHub Blog
- メルカリShops で実際に利用しているプラクティスのようです: メルカリShops の CI/CD と Pull Request 環境
ベストプラクティスも参照してください。
ビルドを高速化する際のおすすめの方法 | Cloud Build のドキュメント | Google Cloud
3. ビルドイメージのクリーンアップ
【課題】 ビルドしたコンテナイメージは Artifact Registry に保存されるが、古くなったイメージを消したいです。
【改善アドバイス】 指定した日数(TTL)で自動的に消えるライフサイクルが指定できるほか、細かい条件を指定できるgcr-cleanerも公開されているのでそれが使えそうです。catnoseさんがまさにこのふたつに言及していました。
Artifact Registryの古いコンテナイメージをCloud Buildから自動削除する
4. 本番環境用の運用サーバー
【課題】 データ洗い替えやRakeタスクの実行など、まれに運用サーバーが必要になるシーンがあります。いまは、App Engine Flexible環境を停止状態で維持し、必要になったタイミングで起動、SSHして実行という流れを踏んでいますが、せっかくコンテナイメージをビルドしているのでいい感じに使えると嬉しいです。Cloud Run Jobs が使えるのでしょうか?
【改善アドバイス】 Cloud Workstations(プレビュー)が用途に合っていると思います。コンテナイメージからインスタンスを起動でき、Cloud Codeのインタフェースで利用できます。
図のようにターミナルも起動できるので、Ruby on Rails のRakeタスクも実行できるはずです。Zennで紹介記事も書いていますので、そちらもごらんください。
Google Cloud の Cloud Workstations (プレビュー)を使ってみよう
5. 開発者の人数が増えたときにスケールするか
【課題】 少人数での運用ということで、人の手、人の目がまだ組み込まれているデプロイフローで、大きな問題にはなっていないですが、人数が増えてきたときに不安があります。
【改善アドバイス】 割り切って完全に自動化するのも手です。
- Cloud Run へ新しいリビジョンを作成した後は、ただちにトラフィックを流すが、100%流さずにカナリアリリースとする
- SLOや稼働時間チェックなどの監視項目メトリクスを収集し、カナリアリリースしたバージョンの品質を判定する
- 品質基準を満たしている場合はトラフィックを100%流す
- 以上を自動で行うようにする
おわりに
ZennのCI/CDを共有するとともに、課題に感じているポイントについて助言をもらいました。なかには、Google Cloudはあまり関係ないものもありますが、いい機会だったので聞いてしましました。改善アドバイスをいただいた感想です:
- ぼんやりと課題と感じていて、ぼんやり改善点をイメージしていたものが、ハッキリ言葉にしていただくことで再認識できました(イメージ共通化のトレードオフなど)
- Cloud Workstations は知りませんでした。というよりは、なんとなくリモートデスクトップ的なサービスだと思いこんでいました。コンテナイメージから起動できると知り、さっそく試してみたくなりました
- リリース後はどうしても自分の目で確認したくなりますが、そこも手作業の部類になってしまい、スケールを阻害する要因になりかねないと改めて認識しました。すぐに完全自動化に踏み切る勇気はまだないですが、そういう選択肢があることを意識できるようになりました
どのクラウドサービスもそうですが、Google Cloudも例にもれず日々たくさんの機能がリリースされ、改善されています。それらすべてを私たちが把握してプロダクトに反映するのは至難の業なので、今回のようにプロフェッショナルの力を借りるのはとても有意義でした。みなさま、ありがとうございました。
さいごに、Cloud Run をコアサービスに据えたCI/CDとして、さきほども少し言及しましたがメルカリShopsさんの事例がとても参考になります。KAUCHE(カウシェ)さんとCI/CDについて対談しているTalkセッションが公開されているので、ぜひご覧になってください。3回見ました。